﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace ZerAx.Net
{
    public class InnerUdpConnection : IConnection
    {
        public readonly RingMemoryStream readStream = new();
        public bool isConnecting;

        private readonly Queue<Packet> msgToSend = new();

        public readonly Socket sender;
        public readonly EndPoint target;
        public EndPoint TargetEP => target;
        internal InnerUdpConnection(Socket udp, EndPoint target)
        {
            sender = udp;
            isConnecting = true;
            this.target = target;
        }

        internal void Write(byte[] buffer, int offset, int count)
        {
            var temp = readStream.Position;
            readStream.Seek(0, SeekOrigin.End);
            readStream.Flush();

            readStream.Write(buffer, offset, count);
                
            readStream.Position = temp;
            readStream.Flush();
        }

        public bool IsConnecting => isConnecting;

        public void Disconnect()
        {
            Send(new Packet(Packet.TYPE_DISCONNECT));
            isConnecting = false;
        }

        public bool Poll(out Packet packet)
        {
            var ans = (packet = Packet.From(readStream)) != null;
            if (packet.typeId == Packet.TYPE_DISCONNECT)
            {
                isConnecting = false;
            }
            return ans;
        }

        public void Send(Packet packet)
        {
            msgToSend.Enqueue(packet);
        }

        public void Update()
        {
            if (!IsConnecting) return;

            if (sender.Poll(0, SelectMode.SelectWrite))
            {
                while (msgToSend.Count > 0)
                {
                    sender.SendTo(msgToSend.Dequeue().GetBytes(), target);
                }
            }
        }
    }
}
